// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import BaseCharacterElement from "../Characters/BaseCharacterElement";
import GameEvent from "../Commons/GameEvent";
import { CharacterType } from "../Enums/GameEnum";
import { UINames } from "../Enums/UIEnum";
import { randomRange } from "../GlobalFunction";
import AudioManager, { AudioEffectType } from "../Managers/AudioManager";
import GameManager, { GameModel } from "../Managers/GameManager";
import PoolManager from "../Managers/PoolManager";
import SaveManager from "../Managers/SaveManager";
import UIManager from "../Managers/UIManager";
import CardManager from "../Models/Cards/CardManager";
import CharacterEntity from "../Models/Characters/CharacterEntity";
import CharacterManager from "../Models/Characters/CharacterManager";
import CharacterTemplate from "../Models/Characters/CharacterTemplate";
import FuBenManager from "../Models/FuBens/FuBenManager";
import GateManager, { GateEvent } from "../Models/Gates/GateManager";
import MapManager, { MapEvent } from "../Models/Maps/MapManager";
import PetEntity from "../Models/Pets/PetEntity";
import PetManager, { PetEvent } from "../Models/Pets/PetManager";
import ShopManager from "../Models/Shops/ShopManager";
import TaskManager from "../Models/Tasks/TaskManager";
import { MovieClipEvent } from "../UIs/UIs/MovieClipUI";

const { ccclass, property } = cc._decorator;

@ccclass
export default class CombatComponent extends cc.Component {

    @property([cc.Node])
    public pathList: cc.Node[] = [];
    @property([cc.Node])
    fubenPathList: cc.Node[] = [];
    @property(cc.Sprite)
    bg: cc.Sprite = null;
    @property(cc.Sprite)
    pos0: cc.Sprite = null;
    @property(cc.Sprite)
    pos1: cc.Sprite = null;
    @property(cc.Sprite)
    pos2: cc.Sprite = null;
    @property(cc.Sprite)
    platform0: cc.Sprite = null;
    @property(cc.Sprite)
    platform1: cc.Sprite = null;
    @property(cc.Sprite)
    platform2: cc.Sprite = null;
    @property(cc.Sprite)
    platform3: cc.Sprite = null;
    @property(cc.Sprite)
    enterIcon: cc.Sprite = null;
    @property(cc.Sprite)
    exitIcon: cc.Sprite = null;
    @property(sp.Skeleton)
    petSkeleton: sp.Skeleton = null;
    @property(cc.Node)
    guideHand: cc.Node = null;

    private enemyEy: CharacterEntity;
    private enemyList: BaseCharacterElement[] = [];
    public static startCombat: boolean;

    protected onLoad(): void {
        for (const iterator of this.fubenPathList) {
            iterator.active = false;
        }
    }

    protected onEnable(): void {
        cc.director.getPhysicsManager().enabled = true;
        // cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
        //     cc.PhysicsManager.DrawBits.e_jointBit |
        //     cc.PhysicsManager.DrawBits.e_shapeBit;
        GameEvent.eventNode.on(GameEvent.MAKECHARACTER_EVENT, this.onMakeCharacter, this);
        GameEvent.eventNode.on(GameEvent.DEADENEMY_EVENT, this.onDeadEnemy, this);
        GameEvent.eventNode.on(MapEvent.SELECTMAP_EVENT, this.onSelectMap, this);
        GameEvent.eventNode.on(PetEvent.PETFIGHT_EVENT, this.onUpdataPet, this);
        GameEvent.eventNode.on(PetEvent.PETTAKEOFF_EVENT, this.onUpdataPet, this);
        GameEvent.eventNode.on(MovieClipEvent.PLAYOVER_EVENT, this.onPlayOver, this);
        GameEvent.eventNode.on(GateEvent.RESETGATE_EVENT, this.onResetGate, this);
        GameEvent.eventNode.on(GameEvent.STARTFUBEN_EVENT, this.OnStartFuBen, this);
        GameEvent.eventNode.on(GameEvent.ENDFUBEN_EVENT, this.OnEndFuBen, this);

        if (SaveManager.single.userdata.isPlayMovie) {
            this.initCombat();
        }

        this.drawScene();
        this.onUpdataPet();
    }
    private initCombat() {
        CombatComponent.startCombat = false;

        this.scheduleOnce(() => {
            CombatComponent.startCombat = true;
            var userdata = SaveManager.single.userdata;
            // userdata.gateEntity.currentGateId = 116;
            var gateTp = GateManager.single.getGateTemplate(userdata.gateEntity.currentGateId);
            GateManager.single.challengeTime = gateTp.challengeTime;
            this.makeGateEnemy();
        }, 2);
    }

    protected onDisable(): void {
        cc.director.getPhysicsManager().enabled = false;
        GameEvent.eventNode.off(GameEvent.MAKECHARACTER_EVENT, this.onMakeCharacter, this);
        GameEvent.eventNode.off(GameEvent.DEADENEMY_EVENT, this.onDeadEnemy, this);
        GameEvent.eventNode.off(MapEvent.SELECTMAP_EVENT, this.onSelectMap, this);
        GameEvent.eventNode.off(PetEvent.PETFIGHT_EVENT, this.onUpdataPet, this);
        GameEvent.eventNode.off(PetEvent.PETTAKEOFF_EVENT, this.onUpdataPet, this);
        GameEvent.eventNode.off(MovieClipEvent.PLAYOVER_EVENT, this.onPlayOver, this);
        GameEvent.eventNode.off(GateEvent.RESETGATE_EVENT, this.onResetGate, this);
        GameEvent.eventNode.off(GameEvent.STARTFUBEN_EVENT, this.OnStartFuBen, this);
        GameEvent.eventNode.off(GameEvent.ENDFUBEN_EVENT, this.OnEndFuBen, this);
    }
    OnStartFuBen(tp: CharacterTemplate) {
        this.platform0.node.active = this.platform1.node.active = this.platform2.node.active = false;
        for (const iterator of this.pathList) {
            iterator.active = false;
        }
        this.clearElement(CharacterType.player);
        this.clearElement(CharacterType.enemy);

        for (const iterator of this.fubenPathList) {
            iterator.active = true;
        }
        CombatComponent.startCombat = false;
        FuBenManager.single.challengeTime = 60;
        this.scheduleOnce(() => {
            CombatComponent.startCombat = true;
            this.makeFubenEnemy(tp);
        }, 0.5);
    }
    OnEndFuBen() {
        for (const iterator of this.fubenPathList) {
            iterator.active = false;
        }
        this.platform0.node.active = this.platform1.node.active = this.platform2.node.active = true;
        for (const iterator of this.pathList) {
            iterator.active = true;
        }

        this.restartGate();
    }
    onResetGate() {
        var arr: cc.Node[] = this.node.children;
        var arr2: BaseCharacterElement[] = [];
        for (const iterator of arr) {
            var ele = iterator.getComponent(BaseCharacterElement);
            if (ele != null) {
                arr2.push(ele);
            }
        }

        while (arr2.length > 0) {
            var ele = arr2.pop();
            ele.deadToDo();
        }

        this.initCombat();
    }
    onPlayOver() {
        this.initCombat();
    }
    onUpdataPet() {
        var userdata = SaveManager.single.userdata;
        var petEy = PetManager.single.getPetEntity(userdata.petWearList[0]);
        if (petEy != null) {
            cc.resources.load("pets/" + petEy.petTp.petSkelentonName, sp.SkeletonData, (error: Error, assets: sp.SkeletonData) => {
                this.petSkeleton.skeletonData = assets;
                this.petSkeleton.setAnimation(0, "idle1", true);
            });
        } else {
            this.petSkeleton.skeletonData = null;
        }
    }
    drawScene() {
        var mapId = SaveManager.single.userdata.currentMapId;
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/bg", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.bg.spriteFrame = spriteFrame;
        });
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/enterIcon", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.enterIcon.spriteFrame = spriteFrame;
        });
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/exitIcon", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.exitIcon.spriteFrame = spriteFrame;
        });
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/platform_0", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.platform3.spriteFrame = spriteFrame;
        });
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/platform_1", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.platform0.spriteFrame = this.platform2.spriteFrame = spriteFrame;
        });
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/platform_2", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.platform1.spriteFrame = spriteFrame;
        });
        cc.resources.load("CombatSceneRes/Scene" + mapId + "/interceptionIcon", cc.SpriteFrame, (error: Error, spriteFrame: cc.SpriteFrame) => {
            this.pos0.spriteFrame = this.pos1.spriteFrame = this.pos2.spriteFrame = spriteFrame;
        });

    }
    onSelectMap() {
        this.drawScene();
    }
    onDeadEnemy(enemy: CharacterEntity) {

        if (GameManager.single.gameModel == GameModel.FuBenModel) {
            var userdata = SaveManager.single.userdata;
            var maptp = MapManager.single.getMapTemplate(userdata.currentMapId);
            var addGoleNum = 0;
            if (maptp != null) {
                addGoleNum = Math.ceil(enemy.gold * (1 + maptp.goldAdd * 0.01));
            } else {
                addGoleNum = enemy.gold;
            }
            if (userdata.perpetualCard != null) {
                addGoleNum *= 2;
            } else if (userdata.monthCard != null && !userdata.monthCard.isOutDate) {
                addGoleNum *= 1.5;
            }

            userdata.gold += Math.ceil(addGoleNum);
            AudioManager.single.playEffect(AudioEffectType.goldDrop);
            TaskManager.single.requestUpdataTaskPregress(103, Math.ceil(addGoleNum));
            TaskManager.single.requestUpdataTaskPregress(101, 1);

            UIManager.single.showDialog("悬赏挑战成功，获得" + Math.ceil(addGoleNum) + "金币。");
            GameEvent.eventNode.emit(GameEvent.ENDFUBEN_EVENT);
            SaveManager.single.saveData();
        } else {

            GateManager.single.enemyNum--;
            var userdata = SaveManager.single.userdata;
            var maptp = MapManager.single.getMapTemplate(userdata.currentMapId);
            var addGoleNum = 0;
            if (maptp != null) {
                addGoleNum = Math.ceil(enemy.gold * (1 + maptp.goldAdd * 0.01));
            } else {
                addGoleNum = enemy.gold;
            }
            if (userdata.perpetualCard != null) {
                addGoleNum *= 2;
            } else if (userdata.monthCard != null && !userdata.monthCard.isOutDate) {
                addGoleNum *= 1.5;
            }

            userdata.gold += Math.ceil(addGoleNum);
            AudioManager.single.playEffect(AudioEffectType.goldDrop);
            TaskManager.single.requestUpdataTaskPregress(103, Math.ceil(addGoleNum));
            TaskManager.single.requestUpdataTaskPregress(101, 1);

            if (GateManager.single.enemyNum <= 0) {
                //下一波
                GateManager.single.currentWave++;

                if (GateManager.single.currentWave >= 5) {

                    var gateTp = GateManager.single.getGateTemplate(userdata.gateEntity.currentGateId);
                    if (userdata.isFirstPassGate(userdata.gateEntity.currentGateId)) {
                        userdata.diamond += Number(gateTp.firstReward);
                        UIManager.single.showTips("钻石 +" + gateTp.firstReward + "。");
                        TaskManager.single.requestUpdataTaskPregress(108, 1);
                        TaskManager.single.requestUpdataTaskPregress(109, Number(gateTp.firstReward));
                    }
                    if (gateTp.heroReward != "0") {
                        CharacterManager.single.requestUnlockHero(Number(gateTp.heroReward));
                    }
                    if (userdata.gatePassList.indexOf(userdata.gateEntity.currentGateId) == -1) {
                        userdata.gatePassList.push(userdata.gateEntity.currentGateId);

                    }
                    userdata.gateEntity.currentGateId = gateTp.nextId;
                    GateManager.single.currentWave = 0;
                    ///设置挑战时间
                    gateTp = GateManager.single.getGateTemplate(userdata.gateEntity.currentGateId);
                    GateManager.single.challengeTime = gateTp.challengeTime;
                    //存档
                    SaveManager.single.saveData();
                    this.scheduleOnce(() => {
                        PetManager.single.requseUnlockWear();
                    });
                }
                this.scheduleOnce(() => {
                    this.makeGateEnemy();
                }, 0.5);

            }
            GameEvent.eventNode.emit(GateEvent.GATEUIUPDATA_EVENT);
            GameEvent.eventNode.emit(GameEvent.CURRENCYUPDATA_EVENT);
        }
    }
    clearElement(type: CharacterType) {
        var arr: cc.Node[] = this.node.children;
        var clearEles: BaseCharacterElement[] = [];
        for (const iterator of arr) {
            var ele = iterator.getComponent(BaseCharacterElement);
            if (ele == null) {
                continue;
            }
            if (ele.characterType == type) {
                clearEles.push(ele);
            }
        }
        for (const iterator of clearEles) {
            iterator.deadToDo();
        }
    }

    onMakeCharacter(characterEy: CharacterEntity) {
        var characterNode = PoolManager.single.getNode(characterEy.characterTp.resName);
        this.node.addChild(characterNode);
        let posArr: cc.Node[] = this.pathList;
        if (GameManager.single.gameModel == GameModel.FuBenModel) {
            posArr = this.fubenPathList;
        }

        characterNode.setPosition(posArr[0].position);
        var characterEle = characterNode.getComponent(BaseCharacterElement);
        characterEle.buildData(characterEy);
        if (CardManager.single.isHaveMonthCard()) {
            characterEle.attribute.attack *= 1.1;
        }
        if (ShopManager.single.attackTime > 0) {
            characterEle.attribute.attack *= 1.5;
        }
        if (ShopManager.single.moveSpeedTime > 0) {
            characterEle.attribute.moveSpeed *= 1.5;
        }

        TaskManager.single.requestUpdataTaskPregress(102, 1);
    }

    makeFubenEnemy(tp: CharacterTemplate) {
        if (this.enemyList != null && this.enemyList.length > 0) {
            while (this.enemyList.length > 0) {
                var ele = this.enemyList.pop();
                if (ele.node.parent != null) {
                    ele.deadToDo();
                }
            }
        }

        if (this.enemyEy == null) {
            this.enemyEy = new CharacterEntity({ id: 0, lv: 0 });
        }

        var enemyNode = PoolManager.single.getNode(tp.resName);
        this.enemyEy.init({ id: tp.id, lv: 200 });
        this.node.addChild(enemyNode);
        enemyNode.setPosition(0, -70);
        var enemyEle = enemyNode.getComponent(BaseCharacterElement)
        this.enemyList.push(enemyEle);
        enemyEle.buildData(this.enemyEy);
    }

    makeGateEnemy() {
        if (this.enemyList != null && this.enemyList.length > 0) {
            while (this.enemyList.length > 0) {
                var ele = this.enemyList.pop();
                if (ele.node.parent != null) {
                    ele.deadToDo();
                }
            }
        }

        if (this.enemyEy == null) {
            this.enemyEy = new CharacterEntity({ id: 0, lv: 0 });
        }
        var userdata = SaveManager.single.userdata;
        var gateTp = GateManager.single.getGateTemplate(userdata.gateEntity.currentGateId);
        var waveTp = GateManager.single.getWaveTemplate(gateTp.waveId);
        var waveData: string = waveTp["wave" + (GateManager.single.currentWave + 1)];
        var enemyInfos: string[] = waveData.split(",");
        for (let i = 0; i < enemyInfos.length; i++) {
            const element = enemyInfos[i].split(":");
            var id = Number(element[0]);
            var num = Number(element[1]);
            var lv = Number(element[2]);
            var posx = randomRange(-50, 100);
            var posy = this.pathList[1 + i].y - 25;
            var characterTp = CharacterManager.single.getCharacterTemplate(id);
            var enemyNode = PoolManager.single.getNode(characterTp.resName);
            this.enemyEy.init({ id: id, lv: lv });
            this.node.addChild(enemyNode);
            enemyNode.setPosition(posx, posy);
            var enemyEle = enemyNode.getComponent(BaseCharacterElement)
            this.enemyList.push(enemyEle);
            enemyEle.buildData(this.enemyEy);
            if (i == 1) {
                enemyEle.changeLeftDir();
            } else {
                enemyEle.changeRightDir();
            }

            if (userdata.guideId == 1 && i == 0) {
                if (this.guideHand.parent != null) this.guideHand.removeFromParent();
                this.guideHand.setPosition(0, 0);
                this.guideHand.active = true;
                this.guideHand.getChildByName("txt").getComponent(cc.Label).string = "点击怪物";
                enemyNode.addChild(this.guideHand);

            }
        }


        GateManager.single.enemyNum = enemyInfos.length;

        GameEvent.eventNode.emit(GameEvent.MAKEENEMY_EVENT);
    }

    protected update(dt: number): void {
        if (!CombatComponent.startCombat) {
            return;
        }
        if (GameManager.single.gameModel == GameModel.FuBenModel) {
            if (FuBenManager.single.challengeTime > 0) {
                FuBenManager.single.challengeTime -= dt;
            } else {
                CombatComponent.startCombat = false;
                //副本时间到
                GameEvent.eventNode.emit(GameEvent.ENDFUBEN_EVENT);
                UIManager.single.showDialog("悬赏挑战时间已到，挑战失败。");
            }
        } else {
            if (GateManager.single.challengeTime > 0) {
                GateManager.single.updataChallengeTime(dt);
            } else {
                //时间已到重新开始
                CombatComponent.startCombat = false;
                this.restartGate();
                UIManager.single.showDialog("时间已到，3秒后重新开始挑战关卡。");
            }
        }



        ShopManager.single.updata(dt);
    }

    restartGate() {
        this.clearElement(CharacterType.player);
        this.clearElement(CharacterType.enemy);
        GateManager.single.currentWave = 0;
        GameEvent.eventNode.emit(GateEvent.GATEUIUPDATA_EVENT);

        this.scheduleOnce(() => {
            CombatComponent.startCombat = true;
            var userdata = SaveManager.single.userdata;
            var gateTp = GateManager.single.getGateTemplate(userdata.gateEntity.currentGateId);
            GateManager.single.challengeTime = gateTp.challengeTime;
            this.makeGateEnemy();
            UIManager.single.closeUI(UINames.DialogUI);
        }, 3);


    }




}
